#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from common.utils import LogUtil
from persistent.mapping import PersistentMapping

from web_server.device_proxy import DeviceProxy
from web_server.models.db_client import DBClient
from web_server.models.perm import GroupPerm, PermType, RolePerm, UserPerm
from web_server.models.user import User
from web_server.models.role import Role
from web_server.models.group import Group

logger = LogUtil.get_logger(__name__)

class PermMgr:
    """权限管理器"""
    
    def __init__(self, device_proxy: DeviceProxy, db_client: DBClient):
        self.device_proxy = device_proxy
        self.db_client = db_client
        # 初始化权限映射表
        if not hasattr(self.db_client.root, 'user_perm_mapping'):
            self.db_client.root.user_perm_mapping = PersistentMapping()
        if not hasattr(self.db_client.root, 'role_perm_mapping'):
            self.db_client.root.role_perm_mapping = PersistentMapping()
        if not hasattr(self.db_client.root, 'group_perm_mapping'):
            self.db_client.root.group_perm_mapping = PersistentMapping()
        self.db_client.flush()

    def __del__(self):
        self.destroy()

    def destroy(self):
        self.db_client = None
        self.device_proxy = None

    def get_user_perm(self, key) -> UserPerm:
        """获取用户权限"""
        return self.db_client.root.user_perm_mapping.get(key)
    
    def set_user_perm(self, user_perm: UserPerm):
        """设置用户权限"""
        key = f'{user_perm.username}:{user_perm.project_path}'
        self.db_client.root.user_perm_mapping[key] = user_perm

    def get_role_perm(self, key) -> RolePerm:
        """获取角色权限"""
        return self.db_client.root.role_perm_mapping.get(key)

    def get_group_perm(self, key) -> GroupPerm:
        """获取用户组权限"""
        return self.db_client.root.group_perm_mapping.get(key)

    def get_project_paths(self, user: User, permissions = None):
        """获取用户有权限的项目列表, 包括从用户组权限和role权限."""
        project_paths = []

        user_project_paths = user.project_paths
        for path in user_project_paths:
            key = f'{user.username}:{path}'
            user_perm = self.get_user_perm(key)
            if user_perm is None:
                raise Exception('用户权限不存在')
            if user_perm.has_perms(permissions):
                project_paths.append(path)

        for role in user.roles:
            role_project_paths = role.project_paths
            for path in role_project_paths:
                key = f'{role.rolename}:{path}'
                role_perm = self.get_role_perm(key)
                if role_perm is None:
                    raise Exception('角色权限不存在')
                if role_perm.has_perms(permissions):
                    project_paths.append(path)

        for group in user.groups:
            group_project_paths = group.project_paths
            for path in group_project_paths:
                key = f'{group.groupname}:{path}'
                group_perm = self.get_group_perm(key)
                if group_perm is None:
                    raise Exception('用户组权限不存在')
                if group_perm.has_perms(permissions):
                    project_paths.append(path)
        
        return list(dict.fromkeys(project_paths))

    def grant_user_permission(self, user: User, project_path: str, permissions: [PermType], override: bool = False):
        """给用户授权"""
        key = f'{user.username}:{project_path}'
        user_perm = UserPerm(user.username, project_path, permissions=permissions)
        if not override and project_path not in user.project_paths and self.get_user_perm(key) is None:
            user.project_paths.append(project_path)
            self.set_user_perm(user_perm)
        if override:
            if project_path not in user.project_paths:
                user.project_paths.append(project_path)
            self.set_user_perm(user_perm)
    
    def check_permission(self, user: User, project_path: str, permissions: [PermType] = None):
        """检查用户是否有项目权限"""
        # 检查用户是否有项目权限
        if project_path in user.project_paths:
            key = f'{user.username}:{project_path}'
            user_perm = self.get_user_perm(key)
            if user_perm.has_perms(permissions):
                return True
        # 检查用户是否有角色权限
        for role in user.roles:
            if project_path in role.project_paths:
                key = f'{role.rolename}:{project_path}'
                role_perm = self.get_role_perm(key)
                if role_perm.has_perms(permissions):
                    return True
        # 检查用户是否有用户组权限
        for group in user.groups:
            if project_path in group.project_paths:
                key = f'{group.groupname}:{project_path}'
                group_perm = self.get_group_perm(key)
                if group_perm.has_perms(permissions):
                    return True
        
        return False

    def revoke_user_permission(self, user: User, project_path: str):
        """撤销用户的项目权限"""
        if user and project_path in user.project_paths:
            user.project_paths.remove(project_path)
            # 删除权限映射
            key = f'{username}:{project_path}'
            if key in self.db_client.root.user_perm_mapping:
                del self.db_client.root.user_perm_mapping[key]

    def revoke_role_permission(self, role: Role, project_path: str):
        """撤销角色的项目权限"""
        if role and project_path in role.project_paths:
            role.project_paths.remove(project_path)
            key = f'{rolename}:{project_path}'
            if key in self.db_client.root.role_perm_mapping:
                del self.db_client.root.role_perm_mapping[key]

    def revoke_group_permission(self, group: Group, project_path: str):
        """撤销用户组的项目权限"""
        if group and project_path in group.project_paths:
            group.project_paths.remove(project_path)
            key = f'{groupname}:{project_path}'
            if key in self.db_client.root.group_perm_mapping:
                del self.db_client.root.group_perm_mapping[key]
